home *** CD-ROM | disk | FTP | other *** search
- Path: news.vanderbilt.edu!news
- From: "Marcus H. Mendenhall" <mendenm@ctrvax.vanderbilt.edu>
- Newsgroups: comp.lang.c
- Subject: Re: help with pi algorithm
- Date: Thu, 01 Feb 1996 10:17:56 +0000
- Organization: Vanderbilt University, Nashville, TN, USA
- Message-ID: <31109354.13A1@ctrvax.vanderbilt.edu>
- References: <0fc_9601240111@csource.blaze.net.au> <4ehfmb$1kn@guava.epix.net>
- NNTP-Posting-Host: 129.59.235.1
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Transfer-Encoding: 7bit
- X-Mailer: Mozilla 2.0b6a (Macintosh; I; PPC)
-
- Here is a piece of code I wrote which portably computes PI. I have computer 1,000,000
- digits with a PowerMacintosh (took about a day, if I remember correctly). Notice that the
- iostreams stuff can be easily removed and replaced with standard C-style i/o if you are
- using c and not c++. To compute lots of digits on a PC running in 16-bit mode, you will
- have to declare some things huge. Good Luck.
-
-
- #include <iostream>
- #include <iomanip>
- #include <stdlib.h>
- #include <fp.h>
- #include <profiler.h>
- #include <time.h>
-
- unsigned long longmult(long dwords, unsigned long mult, unsigned long data[]);
- int longdiv(long dwords, long divisor, unsigned long data[], int start);
- int longadd(long dwords, unsigned long src[], unsigned long dst[]);
- int longsub(long dwords, unsigned long src[], unsigned long dst[]);
-
- void main(void)
- {
- unsigned long *sum, *p8, *p57, *p239, *scr;
- clock_t start, stop;
-
- long lwords;
- int zt8=0, zt57=0, zt239=0, index;
-
- ofstream pidata("pi_digits.txt");
-
- cout << "Enter number of longwords: ";
- cin >> lwords;
-
- scr = new unsigned long[lwords];
- sum = new unsigned long[lwords];
- p8 = new unsigned long[lwords];
- p57 = new unsigned long[lwords];
- p239 = new unsigned long[lwords];
-
- if(!p239) {
- cout << "Not enough memory..." << endl;
- exit(1);
- }
-
- start=clock();
-
- #if __profile__
- OSErr err;
-
- err=ProfilerInit(collectDetailed, bestTimeBase, 100, 100);
- if(err) {
- cout << "Profiler open error " << err << endl;
- exit(1);
- }
- #endif
-
- for(int i=0; i<lwords; i++) {
- sum[i]=0; p8[i]=0; p57[i]=0; p239[i]=0;
- }
-
- p8[0]=24; p57[0]=8; p239[0]=4;
- longdiv(lwords, 8, p8, 0);
- longdiv(lwords, 57, p57, 0);
- longdiv(lwords, 239, p239, 0);
-
- index=1;
- while(zt8 < lwords) {
- for(int j=0; j<lwords; j++) scr[j]=p8[j];
- if (zt57 < lwords) longadd(lwords, p57, scr);
- if (zt239 < lwords) longadd(lwords, p239, scr);
- longdiv(lwords, index, scr, zt8 > 0 ? zt8-1 : 0);
- if (index & 2) longsub(lwords, scr, sum);
- else longadd(lwords, scr, sum);
- zt8=longdiv(lwords, 8*8, p8, zt8);
- if(zt57 < lwords) zt57=longdiv(lwords, 57*57, p57, zt57);
- if(zt239 < lwords) zt239=longdiv(lwords, 239*239, p239, zt239);
- index += 2;
- }
-
- stop = clock();
-
- #if __profile__
- err=ProfilerDump("\pPi_Profile.dat");
- if(err) {
- cout << "Profiler dump error " << err << endl;
- }
- ProfilerTerm();
- #endif
-
- cout << "Index = " << index << endl;
-
- for(int i=0; i<lwords; i++) {
- pidata << setw(9) << right << setfill('0') << sum[i] << " ";
- }
- pidata << endl;
- pidata << "Time = " << (float)(stop-start)/CLOCKS_PER_SEC << " seconds" << endl;
- }
-
-
- const static double shift=1000000000.0, shifti=1.0/(1000000000.0),
- epsi = 0.5/(1000000000.0);
-
- /* longdiv divides an arbitrary-precision number represented with long ints by divisor.
- there are 31 sig bits / long int (to leave room for overflows)
- */
- int longdiv(long dwords, long divisor, unsigned long data[], int start)
- {
- register double d, dinv, eps2, carry;
- register double d1, fd, rshift=shift;
- register unsigned long r1;
-
- int zt=0, i;
-
- d=divisor;
- dinv=1.0/d;
- eps2=0.5*dinv;
-
- carry=0.0;
-
- for(i=start; i<dwords; i++) if(data[i]) break; // find non-zero start
-
- zt=i;
-
- for(; i<dwords; i++) {
- #ifndef GENERATINGPOWERPC
- d1=data[i]+carry*rshift;
- r1=(int)(d1*dinv+eps2);
- carry=d1-r1*d;
- data[i]=r1;
- #else
- fd=data[i];
- d1=fd*rshift;
- r1=(int)((fd+carry)*dinv+eps2);
- carry=(carry-r1*d)*rshift+d1;
- data[i]=r1;
- #endif
-
- }
- return zt;
- }
-
- /* longmult multiplies an arbitrary-precision number represented with long ints by mult.
- there are 31 sig bits / long int (to leave room for overflows)
- return value is carry out of highest word.
- */
- unsigned long longmult(long dwords, unsigned long mult, unsigned long data[])
- {
- double carry;
- double m;
-
- carry=0;
- m=mult;
-
- for(int i=dwords-1; i>=0; i--) {
- double d1;
- d1=(data[i]*m)+carry;
- carry=(unsigned long)(d1*shifti+epsi); /* I hope converting to int
- truncates */
- data[i]=(int)(d1-carry*shift);
- }
- return carry;
- }
-
- int longadd(long dwords, unsigned long src[], unsigned long dst[])
- {
- int carry=0;
- unsigned int sum;
- for(int i=dwords-1; i>=0; i--) {
- sum=src[i]+dst[i]+carry;
- if(sum > 1000000000) {
- dst[i]=sum -1000000000;
- carry=1;
- } else {
- dst[i]=sum;
- carry=0;
- };
- }
- return carry;
- }
-
- int longsub(long dwords, unsigned long src[], unsigned long dst[])
- {
- int carry=0;
- int sum;
- for(int i=dwords-1; i>=0; i--) {
- sum=(int)dst[i]-(int)src[i]-carry;
- if(sum < 0) {
- dst[i]=sum + 1000000000;
- carry=1;
- } else {
- dst[i]=sum;
- carry=0;
- }
- }
- return carry;
- }
-